
#include "Iterator.h"
#include "Aggregator.h"
#include <utility>

using namespace npIterator;
using namespace std;


Iterator::Iterator() // : BaseClass()
{
    
}

Iterator::~Iterator()
{
    
}

Iterator::Iterator(const Iterator& cpy) // : BaseClass(cpy)
{
    this->currentIndx = cpy.currentIndx;
    this->aggregator = cpy.aggregator;
}

Iterator& Iterator::operator=(const Iterator& asn)
{
    if (this == &asn)
    {
        return *this;
    }
    else
    {
        // BaseClass::operator=(asn);
        
        //To do
        this->currentIndx = asn.currentIndx;
        this->aggregator = asn.aggregator;
        
        return *this;
    }
}

Iterator::Iterator(Iterator&& mov) noexcept // : BaseClass(move(mov))
{
    this->currentIndx = mov.currentIndx;
    this->aggregator = mov.aggregator;
}

Iterator& Iterator::operator=(Iterator&& mva) noexcept
{
    if (this == &mva)
    {
        return *this;
    }
    else
    {
        // BaseClass::operator=(move(mva));
        
        //To do
        this->currentIndx = mva.currentIndx;
        this->aggregator = mva.aggregator;
        
        return *this;
    }
}

Iterator* Iterator::clone() const
{
    // return nullptr;
    return new Iterator(*this);
}

Iterator* Iterator::steal(void* sft)
{
    Iterator* shf = static_cast<Iterator*>(sft);
    if (this == shf)
    {
        return this;
    }
    else
    {
        if (!shf)
        {
            //new an instance if not abstract.
            shf = new Iterator();
        }
        
        // BaseClass::steal(shf);
        
        //To do
        shf->currentIndx = this->currentIndx;
        shf->aggregator = this->aggregator;
        
        return shf;
    }
}

//other constructors
Iterator::Iterator(weak_ptr<Aggregator> aggregator)
{
    this->currentIndx = 0;
    this->aggregator = aggregator;
}

//public methods
Stuff& Iterator::first() const throw(ErrorEnum)
{
    if (shared_ptr<Aggregator> ag = this->aggregator.lock())
    {
        return ag->getByIndex(0);
    }
    else
    {
        throw ErrorEnum::Unaccessible;
    }
}

Stuff& Iterator::next() throw(ErrorEnum)
{
    if (shared_ptr<Aggregator> ag = this->aggregator.lock())
    {
        size_t tmpCnt = ag->count();

        if (this->currentIndx < tmpCnt)
        {
            this->currentIndx += 1;
        }

        return this->currentIndx == tmpCnt ? ag->getByIndex(this->currentIndx - 1) : ag->getByIndex(this->currentIndx);
    }
    else
    {
        throw ErrorEnum::Unaccessible;
    }
}

bool Iterator::isLast() const throw(ErrorEnum)
{
    if (shared_ptr<Aggregator> ag = this->aggregator.lock())
    {
        return this->currentIndx == ag->count();
    }
    else
    {
        throw ErrorEnum::Unaccessible;
    }
}

Stuff& Iterator::current() const throw(ErrorEnum)
{
    if (shared_ptr<Aggregator> ag = this->aggregator.lock())
    {
        return this->currentIndx == ag->count() ? ag->getByIndex(this->currentIndx - 1) : ag->getByIndex(this->currentIndx);
    }
    else
    {
        throw ErrorEnum::Unaccessible;
    }
}

//protected methods

//private methods

//static part

//others
